package net.wicp.tams.common.micro;

import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;

import com.alibaba.druid.pool.DruidDataSource;

import lombok.extern.slf4j.Slf4j;
import net.wicp.tams.common.Conf;
import net.wicp.tams.common.connector.executor.IBusiManager;
import net.wicp.tams.common.connector.executor.IConfigManager;
import net.wicp.tams.common.connector.executor.busi.KeyConfigManager;
import net.wicp.tams.common.connector.executor.busi.SpringBusiManager;
import net.wicp.tams.common.connector.executor.impl.CommonService;

@Configuration
@Slf4j
public class ConfigInit {
	@Configuration
	@Order(Ordered.HIGHEST_PRECEDENCE)
	protected class InitContext implements ApplicationContextAware, EnvironmentAware {
		@Override
		public void setEnvironment(Environment environment) {
			Properties inputpamas = new Properties();
			Properties tpProps = Conf.copyProperties();
			for (Object key : tpProps.keySet()) {
				String keystr = String.valueOf(key);
				if (environment.containsProperty(keystr)) {
					inputpamas.put(keystr, environment.getProperty(keystr));
				}
			}
			log.info("input parmas:{}", inputpamas.toString());
			Conf.overProp(inputpamas);
		}

		@Override
		public void setApplicationContext(ApplicationContext arg0) throws BeansException {
			// ConfigInit.context = arg0;
		}
	}

	@Configuration
	@ConditionalOnClass(CommonService.class)
	@Order(Ordered.LOWEST_PRECEDENCE)
	public class ConnectionConfig {
		@Bean
		@ConditionalOnMissingBean
		protected IConfigManager createIConfigManager() {
			IConfigManager manage = new KeyConfigManager();
			return manage;
		}

		@Bean
		protected CommonService createExecutor(ApplicationContext context, IConfigManager configManager) {
			CommonService executor = new CommonService();
			IBusiManager busi = new SpringBusiManager(context);
			executor.setBusiManager(busi);
			executor.setConfigManager(configManager);
			return executor;
		}
	}

	@Configuration
	@ConditionalOnClass(name = "com.alibaba.druid.pool.DruidDataSource")
	public class DruidDBConfig {

		@Bean // 声明其为Bean实例
		@Primary // 在同样的DataSource中，首先使用被标注的DataSource
		@ConditionalOnClass(name = "com.alibaba.druid.pool.DruidDataSource")
		public DataSource dataSource() {
			DruidDataSource datasource = new DruidDataSource();
			datasource.setUrl(Conf.get("common.micro.spring.datasource.url"));
			datasource.setUsername(Conf.get("common.micro.spring.datasource.username"));
			datasource.setPassword(Conf.get("common.micro.spring.datasource.password"));
			datasource.setDriverClassName(Conf.get("common.micro.spring.datasource.driverClassName"));
			// configuration
			datasource.setInitialSize(Integer.parseInt(Conf.get("common.micro.spring.datasource.initialSize")));
			datasource.setMinIdle(Integer.parseInt(Conf.get("common.micro.spring.datasource.minIdle")));
			datasource.setMaxActive(Integer.parseInt(Conf.get("common.micro.spring.datasource.maxActive")));
			datasource.setMaxWait(Integer.parseInt(Conf.get("common.micro.spring.datasource.maxWait")));

			datasource.setTimeBetweenEvictionRunsMillis(
					Integer.parseInt(Conf.get("common.micro.spring.datasource.timeBetweenEvictionRunsMillis")));
			datasource.setMinEvictableIdleTimeMillis(
					Integer.parseInt(Conf.get("common.micro.spring.datasource.minEvictableIdleTimeMillis")));
			datasource.setValidationQuery(Conf.get("common.micro.spring.datasource.validationQuery"));
			datasource.setTestWhileIdle(Boolean.getBoolean(Conf.get("common.micro.spring.datasource.testWhileIdle")));
			datasource.setTestOnBorrow(Boolean.getBoolean(Conf.get("common.micro.spring.datasource.testOnBorrow")));
			datasource.setTestOnReturn(Boolean.getBoolean(Conf.get("common.micro.spring.datasource.testOnReturn")));
			datasource.setPoolPreparedStatements(
					Boolean.getBoolean(Conf.get("common.micro.spring.datasource.poolPreparedStatements")));
			datasource.setMaxPoolPreparedStatementPerConnectionSize(Integer
					.parseInt(Conf.get("common.micro.spring.datasource.maxPoolPreparedStatementPerConnectionSize")));
			String filters = Conf.get("common.micro.spring.datasource.filters");
			if (StringUtils.isNotBlank(filters) && !"none".equals(filters)) {
				try {
					datasource.setFilters(filters);
				} catch (SQLException e) {
					log.error("druid configuration initialization filter", e);
				}
			}
			String connectionProperties = Conf.get("common.micro.spring.datasource.connectionProperties");
			if (StringUtils.isNotBlank(connectionProperties) && !"none".equals(connectionProperties)) {
				datasource.setConnectionProperties(connectionProperties);
			}
			return datasource;
		}
	}
}
